package com.wep.fence.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wep.fence.dto.RegionDTO;
import com.wep.fence.dto.RegionQuery;
import com.wep.fence.entity.RegionEntity;
import com.wep.fence.mapper.RegionMapper;
import com.wep.fence.service.RegionService;
import com.wep.fence.util.PageUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-03-18
 */
@Slf4j
@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, RegionEntity> implements RegionService {

    @Resource
    private HttpServletRequest request;

    @Override
    public List<RegionEntity> listByParam(RegionQuery query) {
        LambdaQueryWrapper<RegionEntity> queryWrapper = getQueryWrapper(query);
        return list(queryWrapper);
    }

    @Override
    public IPage<RegionEntity> pageByParam(RegionQuery query) {
        LambdaQueryWrapper<RegionEntity> queryWrapper = getQueryWrapper(query);
        Page pageParam = PageUtils.getInstance().page(request);
        return page(pageParam, queryWrapper);
    }

    @Override
    public RegionEntity getByCode(String code) {
        return getById(code);
    }

    @Override
    public RegionDTO listChildByCode(String code, Integer type) {
        RegionEntity regionEntity = getByCode(code);
        if (regionEntity == null) {
            return null;
        }

        RegionDTO regionDTO = new RegionDTO();
        BeanUtils.copyProperties(regionEntity, regionDTO);

        // 如果类型匹配，直接返回
        if (ObjectUtil.isNotEmpty(type) && type.equals(regionDTO.getType())) {
            return regionDTO;
        }
        // 批量加载所有子节点
        List<RegionDTO> allAreas = this.baseMapper.findAllDescendantsByCode(code, type);

        // 构建树结构
        Map<String, List<RegionDTO>> areaMap = allAreas.stream().collect(Collectors.groupingBy(RegionDTO::getPcode));
        regionDTO.setRegionList(buildTree(regionDTO.getCode(), areaMap));
        return regionDTO;
    }

    @Override
    public List<RegionEntity> listParentByCode(String code) {
        List<RegionEntity> parentAreas = new ArrayList<>();
        RegionEntity regionEntity = getByCode(code);
        parentAreas.add(regionEntity);

        findAllParentAreasRecursive(code, parentAreas);
        return parentAreas;
    }

    /**
     * 递归获取该code下所有的父类
     */
    private void findAllParentAreasRecursive(String code, List<RegionEntity> parentAreas) {
        RegionEntity currentArea = getByCode(code);
        if (currentArea != null && currentArea.getPcode() != null) {
            RegionEntity parentArea = getByCode(currentArea.getPcode());
            if (parentArea != null) {
                parentAreas.add(parentArea);
                findAllParentAreasRecursive(parentArea.getCode(), parentAreas);
            }
        }
    }

    private List<RegionDTO> buildTree(String parentCode, Map<String, List<RegionDTO>> areaMap) {
        List<RegionDTO> children = areaMap.get(parentCode);
        if (children == null) {
            return Collections.emptyList();
        }

        for (RegionDTO child : children) {
            child.setRegionList(buildTree(child.getCode(), areaMap));
        }
        return children;
    }


    private LambdaQueryWrapper<RegionEntity> getQueryWrapper(RegionQuery query) {
        LambdaQueryWrapper<RegionEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CollUtil.isNotEmpty(query.getCodes()), RegionEntity::getCode, query.getCodes());
        queryWrapper.in(CollUtil.isNotEmpty(query.getPcodes()), RegionEntity::getPcode, query.getPcodes());
        queryWrapper.like(StrUtil.isNotEmpty(query.getName()), RegionEntity::getName, query.getName());
        queryWrapper.eq(ObjectUtil.isNotEmpty(query.getType()), RegionEntity::getType, query.getType());
        queryWrapper.likeRight(StrUtil.isNotEmpty(query.getCodePrefix()), RegionEntity::getCode, query.getCodePrefix());
        return queryWrapper;

    }
}
